package com.shunda.ysdgj.manager.service.impl.goods;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseService;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.shunda.ysdgj.common.exception.CustomException;
import com.shunda.ysdgj.common.util.ValidateUtil;
import com.shunda.ysdgj.manager.mapper.goods.GoodsSkuMapper;
import com.shunda.ysdgj.manager.service.goods.GoodsSkuService;
import com.shunda.ysdgj.manager.service.goods.GoodsSkuSpecService;
import com.shunda.ysdgj.manager.service.system.SysUserService;
import com.shunda.ysdgj.model.dto.base.IdsDto;
import com.shunda.ysdgj.model.dto.goods.GoodsSkuFindDto;
import com.shunda.ysdgj.model.entity.goods.GoodsSku;
import com.shunda.ysdgj.model.entity.goods.GoodsSkuSpec;
import com.shunda.ysdgj.model.entity.system.SysUser;
import com.shunda.ysdgj.model.vo.IdVo;
import com.shunda.ysdgj.model.vo.ResultCodeEnum;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@RequiredArgsConstructor
public class GoodsSkuServiceImpl
        extends MPJBaseServiceImpl<GoodsSkuMapper, GoodsSku>
        implements GoodsSkuService, MPJBaseService<GoodsSku> {

    private final SysUserService sysUserService;
    private final GoodsSkuSpecService goodsSkuSpecService;

    public IPage<GoodsSku> findByPage(GoodsSkuFindDto goodsSkuFindDto) {
        if (ValidateUtil.isNotLong(goodsSkuFindDto.getCurrent())) {
            goodsSkuFindDto.setCurrent(1L);
        }
        if (ValidateUtil.isNotLong(goodsSkuFindDto.getSize())) {
            goodsSkuFindDto.setSize(10L);
        }
        MPJLambdaWrapper<GoodsSku> baseWrapper = JoinWrappers
                .lambda(GoodsSku.class);
        if (ValidateUtil.isNotBlank(goodsSkuFindDto.getSkuTitle())) {
            baseWrapper.like(GoodsSku::getSkuTitle, goodsSkuFindDto.getSkuTitle());
        }
        if (ValidateUtil.isInteger(goodsSkuFindDto.getSkuSaleable())) {
            baseWrapper.eq(GoodsSku::getSkuSaleable, goodsSkuFindDto.getSkuSaleable());
        }
        if (ValidateUtil.isInteger(goodsSkuFindDto.getSkuValid())) {
            baseWrapper.eq(GoodsSku::getSkuValid, goodsSkuFindDto.getSkuValid());
        }
        IPage<GoodsSku> page = new Page<>(goodsSkuFindDto.getCurrent(), goodsSkuFindDto.getSize());
        IPage<GoodsSku> goodsSkuPage = getBaseMapper().selectJoinPage(page, GoodsSku.class, baseWrapper);
        List<GoodsSku> goodsSkuList = goodsSkuPage.getRecords();
        for (GoodsSku goodsSku : goodsSkuList) {
            goodsSku.setSkuSpecList(goodsSkuSpecService.findBySkuId(goodsSku.getId()));
        }
        return goodsSkuPage;
    }

    @Transactional
    public boolean add(String token, GoodsSku goodsSku) {
        if (ValidateUtil.isBlank(goodsSku.getSkuTitle())
                || ValidateUtil.isNotDecimal(goodsSku.getSkuPrice())
                || ValidateUtil.isBlank(goodsSku.getSkuSpec())) {
            throw new CustomException(ResultCodeEnum.PARAM_ERROR);
        }
        SysUser sysUser = sysUserService.getUserInfo(token);
        goodsSku.setId(null);
        goodsSku.setSysUserId(sysUser.getId());
        goodsSku.setShopId(sysUser.getShopId());
        if (!save(goodsSku)) {
            throw new CustomException(ResultCodeEnum.FAIL);
        }
        List<GoodsSkuSpec> skuSpecList = goodsSku.getSkuSpecList();
        for (GoodsSkuSpec skuSpec : skuSpecList) {
            skuSpec.setSkuId(goodsSku.getId());
        }
        return goodsSkuSpecService.add(skuSpecList);
    }

    @Transactional
    public boolean modify(GoodsSku goodsSku) {
        if (ValidateUtil.isNotLong(goodsSku.getId())
                || ValidateUtil.isBlank(goodsSku.getSkuTitle())
                || ValidateUtil.isNotDecimal(goodsSku.getSkuPrice())
                || ValidateUtil.isBlank(goodsSku.getSkuSpec())) {
            throw new CustomException(ResultCodeEnum.PARAM_ERROR);
        }
        if (!updateById(goodsSku)) {
            throw new CustomException(ResultCodeEnum.FAIL);
        }
        return goodsSkuSpecService.modify(goodsSku.getId(), goodsSku.getSkuSpecList());
    }

    public boolean modifySaleable(GoodsSku goodsSku) {
        if (ValidateUtil.isNotLong(goodsSku.getId())
                || ValidateUtil.isNotInteger(goodsSku.getSkuSaleable())) {
            throw new CustomException(ResultCodeEnum.PARAM_ERROR);
        }
        return updateById(goodsSku);
    }

    public boolean modifyValid(GoodsSku goodsSku) {
        if (ValidateUtil.isNotLong(goodsSku.getId())
                || ValidateUtil.isNotInteger(goodsSku.getSkuValid())) {
            throw new CustomException(ResultCodeEnum.PARAM_ERROR);
        }
        return updateById(goodsSku);
    }

    @Transactional
    public boolean deleteByIds(IdsDto idsDto) {
        List<Long> ids = idsDto.getIds();
        if (ids.isEmpty()) {
            throw new CustomException(ResultCodeEnum.PARAM_ERROR);
        }
        if (!removeByIds(ids)) {
            throw new CustomException(ResultCodeEnum.FAIL);
        }
        goodsSkuSpecService.deleteBySkuIds(idsDto.getIds());
        return true;
    }

    public List<Long> getIdsBySpuIds(List<Long> ids) {
        MPJLambdaWrapper<GoodsSku> baseWrapper = JoinWrappers
                .lambda(GoodsSku.class)
                .select(GoodsSku::getId)
                .in(GoodsSku::getSpuId, ids);
        return getBaseMapper()
                .selectJoinList(IdVo.class, baseWrapper)
                .stream().map(IdVo::getId).toList();
    }

    @Transactional
    public boolean deleteBySpuIds(List<Long> ids) {
        LambdaQueryWrapper<GoodsSku> baseWrapper = new LambdaQueryWrapper<>();
        if (!remove(baseWrapper.in(GoodsSku::getSpuId, ids))) {
            throw new CustomException(ResultCodeEnum.FAIL);
        }
        goodsSkuSpecService.deleteBySkuIds(getIdsBySpuIds(ids));
        return true;
    }

}
